package com.zt.ftphelper.view;  /**
 * @Description:
 * @author zt
 * @date 09/08/2019 16:46
 */

import com.zt.ftphelper.Config;
import com.zt.ftphelper.Main;
import com.zt.ftphelper.model.FileItem;
import com.zt.ftphelper.model.MyTreeItem;
import com.zt.ftphelper.model.NameObject;
import com.zt.ftphelper.model.TaskItem;
import com.zt.ftphelper.util.ImageUtil;
import com.zt.ftphelper.util.SimpleAlert;
import com.zt.ftphelper.util.Tools;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.text.Text;
import javafx.util.Callback;
import org.apache.commons.io.comparator.DirectoryFileComparator;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;

import static com.zt.ftphelper.Config.*;


public class FileSelectController {

    //fixme 根节点如果是目录，设置根节点图标的时候所有的文件夹图标也变成盘符，暂时都统一成文件夹图标
    //fixme 文件列表内按Ctrl+A全选时，如何设置首行不被选中

    //todo 监视文件夹，当发生变动时刷新文件列表
    //do 关联treeview
    //do 右键菜单，刷新
    //do 保存设置
    //do 图标
    //do 生成文件
    //do 调用程序
    //do 更换按钮
    //todo 自定义排序
    //do taskList
    //do 键盘事件
    //do 根目录的时候，不要有向上

    private Main main;

    /**
     * table当前展示的目录
     */
    private File currentDir;

    /**
     * 起始路径
     */
    private File baseDir;

    /**
     * 当前选中文件或目录
     */
    private File selectedFile;

    private ObservableList<FileItem> fileItems = FXCollections.observableArrayList();


    /**
     * 改变目录操作之后要展示的目录
     */
    private File nextDir;

    /**
     * 记录父目录
     */
    Stack<File> parents = new Stack<>();

    @FXML
    private TableView<FileItem> fileTable;

    @FXML
    private TableView<TaskItem> taskTable;

    @FXML
    private TableColumn<FileItem, NameObject> nameColumn;

    @FXML
    private TableColumn<TaskItem, String> taskColumn;

    @FXML
    private TableColumn<FileItem, String> sizeColumn;

    @FXML
    private ScrollPane treePane;

    private TreeView treeView;




    @FXML
    private void initialize() {



        currentDir = new File(Config.BASE_PATH);


        buildTree();

        loadFileList(currentDir);

        buildFileTable();

        buildTaskTable();

        registerDragEvent();
    }

    @FXML
    private void handleRefresh() {
        loadFileList(currentDir);
    }

    @FXML
    private void handleJumpToLocation() {
        if (selectedFile == null) {
            selectedFile = currentDir;
        }
        Tools.openFolderInExplorer(selectedFile.getAbsolutePath());
    }


    private void buildFileTable() {
        fileTable.setItems(fileItems);
        fileTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        sizeColumn.setCellValueFactory(cellData -> cellData.getValue().sizeProperty());
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        nameColumn.setSortable(false);
        //文件列表图标设置
        nameColumn.setCellFactory(param -> new TableCell<FileItem, NameObject>() {
            @Override
            protected void updateItem(NameObject item, boolean empty) {
                if (item != null) {
                    setText(item.getName());
                    if (item.getPath() == null) {
                        ImageView imageView = new ImageView(new Image("/img/up3.png"));
                        imageView.setFitHeight(16);
                        imageView.setFitWidth(16);
                        setGraphic(imageView);
                    } else {
                        setGraphic(new ImageView(ImageUtil.getFileIcon(new File(item.getPath()))));
                    }

                } else {
                    setText(null);
                    setGraphic(null);
                }
            }
        });

        fileTable.setRowFactory(tv -> {
            TableRow<FileItem> row = new TableRow<>();
            row.setOnMouseClicked(event -> {

                FileItem fileItem = row.getItem();
                if (fileItem != null) {
                    selectedFile = new File(fileItem.getPath());
                    main.setFooter(fileItem.getPath());
                }
                if (event.getClickCount() == DB_CLICK && (!row.isEmpty())) {
                    if (fileItem == null) {
                        System.out.println("File item is null");
                        return;
                    }
                    //返回上一级
                    if (fileItem.getName().equals(new NameObject("", PARENT_DIR, TYPE_DIR))) {

                        nextDir = currentDir.getParentFile();

                        if (nextDir != null && !nextDir.equals(new File(Config.BASE_PATH).getParentFile())) {
                            currentDir = nextDir;
                        } else {
                            nextDir = currentDir;
                        }

                        loadFileList(nextDir);
                        //展开当前目录
                    } else {

                        nextDir = selectedFile;
                        if (nextDir.exists() && nextDir.isDirectory() && nextDir.canRead()) {
                            currentDir = nextDir;
                            loadFileList(nextDir);
                        } else if (nextDir.isFile() && nextDir.canExecute()) {
                            try {
                                if (Desktop.isDesktopSupported()) {
                                    if (Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
                                        Desktop.getDesktop().open(nextDir);
                                    }

                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            });
            return row;
        });

    }

    private void buildTaskTable() {
        taskTable.setPlaceholder(new Text("拖拽文件到此处"));
        taskTable.setItems(Config.getInstance().getTaskData());
        taskColumn.setCellValueFactory(new PropertyValueFactory<>("path"));

        taskTable.setRowFactory(tableView -> {
            final TableRow<TaskItem> row = new TableRow<>();
            final ContextMenu contextMenu = new ContextMenu();
            final MenuItem removeMenuItem = new MenuItem("删除");
            removeMenuItem.setStyle("-fx-pref-width: 120px; ");
            ContextMenu contextMenu2 = new ContextMenu();
            MenuItem clearMenuItem = new MenuItem("清除");
            clearMenuItem.setStyle("-fx-pref-width: 120px; ");
            contextMenu2.getItems().add(clearMenuItem);
            clearMenuItem.setOnAction(event -> clearTaskData());
            removeMenuItem.setOnAction(event -> taskTable.getItems().remove(row.getItem()));
            contextMenu.getItems().add(removeMenuItem);
            contextMenu.getItems().add(clearMenuItem);
            // Set context menu on row, but use a binding to make it only show for non-empty rows:
            row.contextMenuProperty().bind(
                    Bindings.when(row.emptyProperty())
                            .then(contextMenu2)
                            .otherwise(contextMenu)
            );
            return row;
        });
    }

    /**
     * 注册拖放事件
     */
    private void registerDragEvent() {
        if (treeView == null) {
            return;
        }
        fileTable.setOnDragDetected(event -> {
            Dragboard db = fileTable.startDragAndDrop(TransferMode.ANY);
            ClipboardContent content = new ClipboardContent();
            StringBuilder sb = new StringBuilder();
            ArrayList<File> files = new ArrayList<>();
            fileTable.getSelectionModel().getSelectedItems().forEach(e -> {
                files.add(new File(e.getPath()));
                sb.append(e.getPath() + ",");
            });
            content.putFiles(files);
            String paths = "";
            if (sb.indexOf(",") > 0) {
                paths = sb.deleteCharAt(sb.lastIndexOf(",")).toString();
            }
            content.putString(paths);
            db.setContent(content);
            event.consume();
        });

        treeView.setOnDragDetected(event -> {
            Dragboard db = treeView.startDragAndDrop(TransferMode.ANY);
            ClipboardContent content = new ClipboardContent();
            StringBuilder sb = new StringBuilder();

            treeView.getSelectionModel().getSelectedItems().forEach(e -> sb.append(e + ","));
            String paths = sb.deleteCharAt(sb.lastIndexOf(",")).toString();

            content.putString(paths);
            db.setContent(content);
            event.consume();
        });


        taskTable.setOnDragOver(event -> {
            Dragboard db = event.getDragboard();
            if (db.hasString()) {
                event.acceptTransferModes(TransferMode.COPY);
            }
            event.consume();
        });


        taskTable.setOnDragDropped(event -> {
            Dragboard db = event.getDragboard();
            boolean success = false;
            if (db.hasString()) {
                ArrayList<String> newList = new ArrayList<>(Arrays.asList(db.getString().split(",")));
                newList.forEach(e -> {
                    if (!Config.getInstance().getTaskData().contains(new TaskItem(e))) {
                        Config.getInstance().getTaskData().add(new TaskItem(e));
                    }
                });
                success = true;
            }

            event.setDropCompleted(success);
            event.consume();
        });
    }

    /**
     * 载入文件列表
     *
     * @param dir
     */

    public void loadFileList(File dir) {
        if (dir.exists() && dir.isDirectory()) {
            expandTreeToDir(dir);
            try {
                if (dir.exists() && dir.canRead()) {
                    clearFileData();
                    if (dir.getParent() != null && !dir.equals(new File(Config.BASE_PATH))) {
                        fileItems.add(new FileItem());
                    }
                    Arrays.stream(dir.listFiles())
                            .sorted(DirectoryFileComparator.DIRECTORY_COMPARATOR)
                            .filter(e -> e.canRead() && !e.isHidden())
                            .forEach(f -> fileItems.add(getFileItemFromFile(f)));
                }
//                fileItems.forEach(e-> System.out.println(e.getName()));

            } catch (Exception e) {
                clearFileData();

            }
        }
    }

    public void expandTreeToDir(File dir) {
        parents.clear();
        parents.push(dir);
        pushParentIntoStack(dir);
        treeView.getRoot().setExpanded(true);
        setExpand(treeView.getRoot(), parents);
    }

    /**
     * 把file转成fileItem
     *
     * @param file
     * @return
     */
    public FileItem getFileItemFromFile(File file) {
        return new FileItem(file.getPath(), file.getName(), file.isDirectory() ? "d" : "f", file.isDirectory() ? "0" : String.valueOf(file.getTotalSpace()));
    }

    /**
     * 清除文件数据
     */
    public void clearFileData() {
        fileItems.remove(0, fileItems.size());
    }

    /**
     * 清除文件数据
     */
    @FXML
    public void clearTaskData() {
        fileItems.clear();
    }

    /**
     * 创建tree
     *
     * @return
     */
    public TreeView buildTree() {

        if (!new File(Config.BASE_PATH).exists()) {
            new SimpleAlert("初始化目录失败，请重新设置起始目录");
            return null;
        }
        treeView = new TreeView<>(new MyTreeItem(new File(Config.BASE_PATH)));
        //刷新默认选中root，这样


        treeView.setCellFactory(new Callback<TreeView<File>, TreeCell<File>>() {
            @Override
            public TreeCell<File> call(TreeView<File> arg0) {
                return new TreeCell<File>() {
                    @Override
                    protected void updateItem(File f, boolean empty) {
                        super.updateItem(f, empty);
                        if (empty) {
                            setText(null);
                            setGraphic(null);
                        } else {
                            if (f.getParent() == null) {
                                setText(f.getPath());
                            } else {
                                setText(f.getName());
                            }
                            if (f.isDirectory()) {
                                setGraphic(new ImageView(ImageUtil.getDirIcon()));
                            } else {
                                setGraphic(null);
                            }
                        }
                    }
                };
            }
        });
        treeView.getRoot().setExpanded(true);
        treePane.setContent(treeView);

        //关联fileList
        treeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            TreeItem<File> currentSelectItem = (TreeItem<File>) newValue;
            if (currentSelectItem != null && currentSelectItem.getValue() != null) {
                File file = new File(currentSelectItem.getValue().getPath());
                if (file.exists() && file.isDirectory()) {
                    currentDir = file;
                    loadFileList(currentDir);
                    main.setFooter(file.getPath());
                }
            }
        });

        ContextMenu contextMenu = new ContextMenu();
        MenuItem menuItem = new MenuItem("刷新");
        menuItem.setStyle("-fx-pref-width: 120px; ");
        menuItem.setOnAction(event -> handleRefresh());
        contextMenu.getItems().add(menuItem);
        treeView.setContextMenu(contextMenu);
        return treeView;
    }

    /**
     * 把文件夹的父目录存进堆栈
     *
     * @param file
     */
    private void pushParentIntoStack(File file) {

        if (file.getParentFile() != null && !file.getParentFile().equals(new File(Config.BASE_PATH))) {
            parents.push(file.getParentFile());
            pushParentIntoStack(file.getParentFile());
        }
    }

    /**
     * 递归设置节点展开
     *
     * @param treeItem
     * @param stack
     * @return
     */
    private void setExpand(TreeItem<File> treeItem, Stack<File> stack) {

        if (!stack.empty()) {
            File file = stack.pop();
            for (int i = 0; i < treeItem.getChildren().size(); i++) {
                TreeItem<File> findItem = treeItem.getChildren().get(i);
                if (findItem.getValue().equals(currentDir)) {
                    if (treeView.getRow(findItem) > 13) {
                        treeView.scrollTo(treeView.getSelectionModel().getSelectedIndex());
                    } else {
                        treeView.scrollTo(0);
                    }
                    treeView.getSelectionModel().select(findItem);
                }
                if (findItem.getValue().equals(file)) {
                    findItem.setExpanded(true);
                    setExpand(findItem, stack);
                }
            }
        }
    }


    public void setMain(Main main) {
        this.main = main;
    }

}
